﻿
using System;
using System.Linq;
using System.Threading.Tasks;
using System.Windows.Media;
using Buddy.Coroutines;
using ff14bot;
using ff14bot.Enums;
using ff14bot.Helpers;
using ff14bot.Managers;
using ff14bot.Objects;
using RebornCo.Helpers;
using RebornCo.Settings;
using TreeSharp;

namespace RebornCo.Rotations
{
    public class Ninja : RebornCoRoutine
    {
        public override void OnInitialize()
        {
            WantHealing = false;
            WindowSettings = new RogueSetting();
            if (RogueSettings.UseOpener) Target.TargetChanged = true;
        }
        public sealed override ClassJobType[] Class
        {
            get
            {
                return new[] 
                { ClassJobType.Rogue, ClassJobType.Ninja};
            }
        }
        public static RogueSetting RogueSettings
        {
            get { return WindowSettings as RogueSetting; }
        }
        public static bool MudraReady;

        [Behavior(BehaviorType.PreCombatBuffs, ClassJobType.Ninja, GameContext.All, 1)]
        public Composite NinjaCreateBasicPreCombatBuffs()
        {
            return new ActionRunCoroutine(ctx => NinjaBuildPreCombatBuffs());
        }
        public static async Task<bool> NinjaBuildPreCombatBuffs()
        {
            if (!IsValid()) return false;

            if (Resting)
            {
                if (!Core.Player.IsCasting && await Spell.Cast("Cure", Core.Player, Core.Player.CurrentHealthPercent < 70 && Core.Player.CurrentHealthPercent < Core.Player.CurrentManaPercent)) return true;
                if (!Core.Player.IsCasting && await Spell.Cast("Physick", Core.Player, Core.Player.CurrentHealthPercent < 70 && Core.Player.CurrentHealthPercent < Core.Player.CurrentManaPercent)) return true;
                return false;
            }

            if (MudraReady && DateTime.UtcNow.TimeOfDay > MudraTimeReady)
            {
                if (!Core.Player.HasAura("Mudra") && (NinjutsuInCooldown() || NinjutusCooldown < 10))
                {
                    Logging.Write(Colors.Orchid, "[RebornCo] No Mudra?");
                    MudraReady = false;
                }
                if ((Core.Player.CurrentTarget != null && Core.Player.CurrentTarget.InLineOfSight() 
                    &&( Core.Player.Distance2D(Core.Player.CurrentTarget.Location) < 15
                        || Spell.NoneGcdLast.Equals("Shuriken") && Core.Player.Distance2D(Core.Player.CurrentTarget.Location) < 25) 
                        || Spell.NoneGcdLast.Equals("Huton") )
                && await CastNinjutsu(Core.Player.CurrentTarget))
                {
                    Logging.Write(Colors.Orchid, "[RebornCo] Casting Ninjutsu");
                }
                return true;
            }
            if (MudraReady) { return false; } 
            if ((Spell.NoneGcdCache == null || Spell.NoneGcdCache.Equals("Huton"))  //check combat
                && (RogueSettings.HutonNoTarget  || (Core.Player.CurrentTarget != null 
                && Core.Player.CurrentTarget.CanAttack && Core.Player.CurrentTarget.InLineOfSight() && Core.Player.Distance2D(Core.Player.CurrentTarget.Location) < 15 )
               && Core.Player.ClassLevel > 44 && NinjutsuCanMudra() && !Core.Player.HasAura("Huton") ))
            {
                Spell.NoneGcdCache = "Huton";
                Logging.Write(Colors.Orchid, "[RebornCo] Preparing Precombat Huton");
                await Coroutine.Wait(4000, () => CastMudra("Jin"));
                MudraSafe = false;
                MudraReady = true;
                if (RogueSettings.MoveStopNinjutsu) Movement.StopMove();
                else await Movement.MoveToTarget();
                await Coroutine.Wait(4000, () => CastMudra("Chi"));
                MudraSafe = false;
                if (!RogueSettings.MoveStopNinjutsu) await Movement.MoveToTarget();
                await Coroutine.Wait(4000, () => CastMudra("Ten"));
                MudraSafe = false;
                MudraTimeReady = DateTime.UtcNow.TimeOfDay + TimeSpan.FromMilliseconds(510);
                return true;
            }
            return MudraReady;
        }
        [Behavior(BehaviorType.PreCombatBuffs)]
        public Composite RogueCreateBasicPreCombatBuffs()
        {
            return new ActionRunCoroutine(ctx => RogueBuildPreCombatBuffs());
        }
        public static async Task<bool> RogueBuildPreCombatBuffs()
        {
            if (Core.Player.CurrentTarget == null || !IsValid()) return false;


            if (await Spell.BuffParty("Protect")) return true;
            if (await Spell.BuffParty("Stoneskin")) return true;
            if (await Spell.Cast("Kiss of the Viper", Core.Player, !(Core.Player.HasAura("Kiss of the Viper")))) return true;
            if (await Spell.Cast("Kiss of the Wasp", Core.Player, !(Core.Player.HasAura("Kiss of the Viper") || Core.Player.HasAura("Kiss of the Wasp")))) return true;

            if (Resting)
            {
                if (!Core.Player.IsCasting && await Spell.Cast("Cure", Core.Player, Core.Player.CurrentHealthPercent < 70 && Core.Player.CurrentHealthPercent < Core.Player.CurrentManaPercent)) return true;
                if (!Core.Player.IsCasting && await Spell.Cast("Physick", Core.Player, Core.Player.CurrentHealthPercent < 70 && Core.Player.CurrentHealthPercent < Core.Player.CurrentManaPercent)) return true;
                return false;
            }
            return await CombatCompanion();
        }

        [Behavior(BehaviorType.Rest)]
        public Composite NinjaCreateBasicRest()
        {
            return new PrioritySelector(
                new Decorator(ctx => Resting && Core.Player.HasAura("Hidden"), 
                    new ActionRunCoroutine(ctx => Spell.Cast("Hide"))),
                new ActionRunCoroutine(ctx => DefaultRestBehavior(Core.Player.CurrentTPPercent))); 
        }
        
        [Behavior(BehaviorType.CombatBuffs, ClassJobType.Adventurer, GameContext.All, 2)]
        public Composite TopCreateBasicCombatBuffs()
        {
            return new ActionRunCoroutine(ctx => TopBuildCombatBuffs());
        }

        public static async Task<bool> TopBuildCombatBuffs()
        {
            ShouldPulse = true;
            await Target.EnsureValidTarget();
            await Movement.MoveToTarget();
            return false;
        }

        [Behavior(BehaviorType.CombatBuffs, ClassJobType.Ninja, GameContext.All, 1)]
        public Composite NinjaCreateBasicCombatBuffs()
        {
            return new ActionRunCoroutine(ctx => NinjaBuildCombatBuffs());
        }
        public static async Task<bool> NinjaBuildCombatBuffs()
        {
            if (MudraReady && Core.Player.CurrentTarget != null && DateTime.UtcNow.TimeOfDay > MudraTimeReady)
            {
                if (!Core.Player.HasAura("Mudra") && (NinjutsuInCooldown() || NinjutusCooldown < 10))
                {
                    Logging.Write(Colors.Orchid, "[RebornCo] No Mudra?");
                    MudraReady = false;
                }
                if ((Core.Player.CurrentTarget != null && Core.Player.CurrentTarget.InLineOfSight()
                    && (Core.Player.Distance2D(Core.Player.CurrentTarget.Location) < 15
                        || Spell.NoneGcdLast.Equals("Shuriken") && Core.Player.Distance2D(Core.Player.CurrentTarget.Location) < 25)
                        || Spell.NoneGcdLast.Equals("Huton"))
                && await CastNinjutsu(Core.Player.CurrentTarget))
                {
                    Logging.Write(Colors.Orchid, "[RebornCo] Casting Ninjutsu");
                }
                return true;
            }
            if (Spell.Opener || Spell.GcdTime < RogueSettings.NoneGcdWindowEnd) return false;
            if (MudraReady) { return true; }
            if ((RogueSettings.HutonNoTarget || Core.Player.CurrentTarget != null && Core.Player.CurrentTarget.InLineOfSight())
                && (Spell.NoneGcdCache == null || Spell.NoneGcdCache.Equals("Huton")) && Core.Player.ClassLevel > 44 && NinjutsuCanMudra()
                && !Core.Player.HasAura("Huton", false, RogueSettings.HutonClip))
            {
                Spell.NoneGcdCache = "Huton";
                Logging.Write(Colors.Orchid, "[RebornCo] Preparing Huton");
                await Coroutine.Wait(4000, () => CastMudra("Jin"));
                MudraSafe = false;
                MudraReady = true;
                if (RogueSettings.MoveStopNinjutsu) Movement.StopMove();
                else await Movement.MoveToTarget();
                await Coroutine.Wait(4000, () => CastMudra("Chi"));
                MudraSafe = false;
                if (!RogueSettings.MoveStopNinjutsu) await Movement.MoveToTarget();
                await Coroutine.Wait(4000, () => CastMudra("Ten"));
                MudraSafe = false;
                MudraTimeReady = DateTime.UtcNow.TimeOfDay + TimeSpan.FromMilliseconds(510);
                return true;
            }

            if (Spell.NoneGcdCache == null && Core.Player.ClassLevel > 49 && Core.Player.CurrentTarget != null 
                && Core.Player.CurrentTarget.IsBehind && NinjutsuCanMudra()
                    && Core.Player.Distance2D(Core.Player.CurrentTarget.Location) < 15 && CanTrick()
                && (RogueSettings.MinHpCustom && RogueSettings.MinHpTrick < Core.Player.CurrentTarget.CurrentHealthPercent
                || !RogueSettings.MinHpCustom && RogueSettings.MinDotHp < Core.Player.CurrentTarget.CurrentHealthPercent)
                && (!RogueSettings.SuitonWaitForIrAndB4B || Spell.GcdMs("Internal Release") > 80 && Spell.GcdMs("Blood for Blood") > 80))
            {
                Spell.NoneGcdCache = "Suiton";
                Logging.Write(Colors.Orchid, "[RebornCo] Preparing Suiton");
                await Coroutine.Wait(4000, () => CastMudra("Ten"));
                MudraSafe = false;
                MudraReady = true;
                if (RogueSettings.MoveStopNinjutsu) Movement.StopMove();
                else await Movement.MoveToTarget();
                await Coroutine.Wait(4000, () => CastMudra("Chi"));
                MudraSafe = false;
                if (!RogueSettings.MoveStopNinjutsu) await Movement.MoveToTarget();
                await Coroutine.Wait(4000, () => CastMudra("Jin"));
                MudraSafe = false;
                MudraTimeReady = DateTime.UtcNow.TimeOfDay + TimeSpan.FromMilliseconds(510);
                return true;
            }
            if (Spell.NoneGcdCache == null && Core.Player.CurrentTarget != null && RogueSettings.Aoe
                    && Core.Player.CurrentTarget.CurrentHealthPercent > RogueSettings.MinNinjutsu
                && Core.Player.ClassLevel > 44 && NinjutsuCanMudra()
                && Target.EnemiesNearTarget(5, Core.Player) > RogueSettings.AoeCount
                     && Movement.IsInSafeMeleeRange(Core.Player.CurrentTarget)
                     && Core.Player.CurrentTarget.InLineOfSight() && !Core.Player.CurrentTarget.HasAura("Doton"))
            {
                Spell.NoneGcdCache = "Doton";
                Logging.Write(Colors.Orchid, "[RebornCo] Preparing Doton");
                await Coroutine.Wait(4000, () => CastMudra("Ten"));
                MudraSafe = false;
                MudraReady = true;
                if (RogueSettings.MoveStopNinjutsu) Movement.StopMove();
                else await Movement.MoveToTarget();
                await Coroutine.Wait(4000, () => CastMudra("Jin"));
                MudraSafe = false;
                if (!RogueSettings.MoveStopNinjutsu) await Movement.MoveToTarget();
                await Coroutine.Wait(4000, () => CastMudra("Chi"));
                MudraSafe = false;
                MudraTimeReady = DateTime.UtcNow.TimeOfDay + TimeSpan.FromMilliseconds(510);
                return true;
            }
            if (Spell.NoneGcdCache == null && Core.Player.ClassLevel > 34 && Core.Player.CurrentTarget != null
                && RogueSettings.Aoe && Core.Player.CurrentTarget.CurrentHealthPercent > RogueSettings.MinNinjutsu
                && Core.Player.CurrentTarget.InLineOfSight() && NinjutsuCanMudra() && Target.EnemiesNearTarget(5) > RogueSettings.AoeCount
                     && Core.Player.Distance2D(Core.Player.CurrentTarget.Location) < 15)
            {
                Spell.NoneGcdCache = "Katon";
                Logging.Write(Colors.Orchid, "[RebornCo] Preparing Katon");
                await Coroutine.Wait(4000, () => CastMudra("Chi"));
                MudraSafe = false;
                MudraReady = true;
                if (RogueSettings.MoveStopNinjutsu) Movement.StopMove();
                else await Movement.MoveToTarget();
                await Coroutine.Wait(4000, () => CastMudra("Ten"));
                MudraSafe = false;
                MudraTimeReady = DateTime.UtcNow.TimeOfDay + TimeSpan.FromMilliseconds(510);
                return true;
            }
            if (Spell.NoneGcdCache == null && Core.Player.CurrentTarget != null && Core.Player.ClassLevel > 29
                && Core.Player.CurrentTarget.CurrentHealthPercent > RogueSettings.MinNinjutsu
                && Core.Player.CurrentTarget.InLineOfSight()
                     && (Core.Player.ClassLevel < 35 || RogueSettings.ShurikenAlways
                     || RogueSettings.ShurikenCheckMobs && RogueSettings.ShurikenList.Any(n => !string.IsNullOrEmpty(n) && Core.Player.CurrentTarget.Name.ToLower().Contains(n)))
                     && Core.Player.Distance2D(Core.Player.CurrentTarget.Location) < 25
                     && (NinjutsuCanMudra() || Spell.NoneGcdLast.Equals("Kassatsu")))
            {
                Spell.NoneGcdCache = "Shuriken";
                Logging.Write(Colors.Orchid, "[RebornCo] Preparing Shuriken!");
                await Coroutine.Wait(4000, () => CastMudra("Ten"));
                MudraSafe = false;
                MudraTimeReady = DateTime.UtcNow.TimeOfDay + TimeSpan.FromMilliseconds(510); 
                MudraReady = true;
                return true;
            }
            if (Spell.NoneGcdCache == null && Core.Player.CurrentTarget != null && Core.Player.ClassLevel > 29
                && Core.Player.CurrentTarget.CurrentHealthPercent > RogueSettings.MinNinjutsu
                && Core.Player.CurrentTarget.InLineOfSight() &&
                     Core.Player.Distance2D(Core.Player.CurrentTarget.Location) < 15 &&
                     (NinjutsuCanMudra() || Spell.NoneGcdLast.Equals("Kassatsu")))
            {
                Spell.NoneGcdCache = "Raiton";
                Logging.Write(Colors.Orchid, "[RebornCo] Preparing Raiton");
                await Coroutine.Wait(4000, () => CastMudra("Ten"));
                MudraSafe = false;
                MudraReady = true;
                if (RogueSettings.MoveStopNinjutsu) Movement.StopMove();
                else await Movement.MoveToTarget();
                await Coroutine.Wait(4000, () => CastMudra("Chi"));
                MudraSafe = false;
                MudraTimeReady = DateTime.UtcNow.TimeOfDay + TimeSpan.FromMilliseconds(510);
                return true;
            }
            return MudraReady;
        }

        [Behavior(BehaviorType.CombatBuffs)]
        public Composite RogueCreateBasicCombatBuffs()
        {
            return new ActionRunCoroutine(ctx => RogueBuildCombatBuffs()); 
        }
        public static async Task<bool> RogueBuildCombatBuffs()
        {
            if (Spell.Opener) return false;
            if (await Spell.Cast("Cure", Core.Player, Core.Player.CurrentHealthPercent < 40)) return true;
            if (await Spell.Cast("Physick", Core.Player, Core.Player.CurrentHealthPercent < 40)) return true;
            //Core.Player.TargetCharacter.CastingSpellId==int.TryParse(n) ||
            if (Spell.GcdTime < RogueSettings.NoneGcdWindowEnd) return false;
            if (RogueSettings.NoneGcdIgnoreShiftingConditions && Spell.NoneGcdCache != null && Spell.NoneGcdCacheTarget != null 
                && !Spell.NoneGcdCache.Equals("Potion"))
                return await Spell.NoneGcdCast(Spell.NoneGcdCache, Spell.NoneGcdCacheTarget, true, true);
            if (await Spell.NoneGcdCast("Jugulate", Core.Player.CurrentTarget, RogueSettings.JugulateCheckSpells
                && Core.Player.TargetCharacter != null && Core.Player.TargetCharacter.IsCasting
                && RogueSettings.JugulateList.Any(n => !string.IsNullOrEmpty(n)
                    && ( Core.Player.TargetCharacter.SpellCastInfo.Name.ToLower().Contains(n))))) return true;
            if (await Spell.NoneGcdCast("Sneak Attack", Core.Player.CurrentTarget, 
                RogueSettings.SneakAttack && RogueSettings.CooldownsUsable && Core.Player.ClassLevel > 21
                && Core.Player.HasAura("Hidden") && Core.Player.CurrentTarget != null && !Core.Player.CurrentTarget.IsFlanking 
                && !Core.Player.CurrentTarget.IsBehind)) return true;
            if (await Spell.NoneGcdCast("Trick Attack", Core.Player.CurrentTarget, RogueSettings.CooldownsUsable && Core.Player.ClassLevel > 49
                && Core.Player.CurrentTarget != null
                && (RogueSettings.MinHpCustom && RogueSettings.MinHpTrick < Core.Player.CurrentTarget.CurrentHealthPercent
                || !RogueSettings.MinHpCustom && RogueSettings.MinDotHp < Core.Player.CurrentTarget.CurrentHealthPercent)
                && (Core.Player.HasAura("Hidden") || Core.Player.HasAura("Suiton") || Spell.NoneGcdLast.Equals("Suiton")) 
                && Core.Player.CurrentTarget != null
                    && (RogueSettings.TrickIsBehindAdjustment != 100 && Movement.IsBehind(Core.Player.CurrentTarget, Core.Player)
                    || RogueSettings.TrickIsBehindAdjustment == 100 && Core.Player.CurrentTarget.IsBehind))) return true;
            if (await Spell.NoneGcdCast("Kassatsu", Core.Player, RogueSettings.CooldownsUsable && Spell.NoneGcdLast.Equals("Trick Attack") && NinjutusCooldown > 1300)) return true;
            if (await Spell.NoneGcdCast("Perfect Dodge", Core.Player, RogueSettings.CooldownsUsable && Core.Player.CurrentHealthPercent < 40)) return true;
            if (await Spell.NoneGcdCast("Invigorate", Core.Player, RogueSettings.CooldownsUsable && Core.Player.CurrentTPPercent < 50)) return true; 
            if (await Spell.NoneGcdCast("Blood for Blood", Core.Player, RogueSettings.CooldownsUsable)) return true;
            if (await Spell.NoneGcdCast("Internal Release", Core.Player, RogueSettings.CooldownsUsable)) return true;
            if (RogueSettings.CooldownsUsable && Spell.Potion != null && Spell.Potion.IsValid
                && Spell.Potion.CanUse(Core.Player) && Spell.Potion.Name.Equals(RogueSettings.PotionName))
            {
                Spell.Potion.UseItem(Core.Player);
                if (RogueSettings.PotionForce) Spell.NoneGcdCache = "Potion";
            }
            if (await Spell.NoneGcdCast("Foresight", Core.Player, RogueSettings.CooldownsUsable && Core.Player.CurrentHealthPercent < 40)) return true; 
            if (await Spell.NoneGcdCast("Eye for an Eye", Core.Player, RogueSettings.CooldownsUsable)) return true;
            if (await Spell.NoneGcdCast("Quelling Strikes", Core.Player, RogueSettings.CooldownsUsable)) return true;
            if (await Spell.NoneGcdCast("Hawk's Eye", Core.Player, RogueSettings.CooldownsUsable)) return true;
            if (await Spell.NoneGcdCast("Bloodbath", Core.Player, RogueSettings.CooldownsUsable)) return true;
            if (await Spell.NoneGcdCast("Raging Strikes", Core.Player, RogueSettings.CooldownsUsable)) return true;
            if (await Spell.NoneGcdCast("Keen Flurry", Core.Player, RogueSettings.CooldownsUsable && Core.Player.CurrentHealthPercent < 80)) return true;
            if (await Spell.NoneGcdCast("Foresight", Core.Player, RogueSettings.CooldownsUsable && Core.Player.CurrentHealthPercent < 60)) return true;
            if (await Spell.NoneGcdCast("Convalescence", Core.Player, RogueSettings.CooldownsUsable && Core.Player.CurrentHealthPercent < 70)) return true;
            if (await Spell.NoneGcdCast("Second Wind", Core.Player, RogueSettings.CooldownsUsable && Core.Player.CurrentHealthPercent < 40)) return true;
            if (await Spell.NoneGcdCast("Awareness", Core.Player, RogueSettings.CooldownsUsable && Core.Player.CurrentHealthPercent < 30))return true;
            if (await Spell.NoneGcdCast("Featherfoot", Core.Player, RogueSettings.CooldownsUsable && Core.Player.Distance2D() < 5)) return true;
            return false;
        }

        [Behavior(BehaviorType.Pull)]
        public Composite NinjaCreateBasicPull()
        {
            return new ActionRunCoroutine(ctx => NinjaBuildPullBehavior()); 
        }
        public static async Task<bool> NinjaBuildPullBehavior()
        {
            if (Core.Player.CurrentTarget != null && !Core.Player.CurrentTarget.CanAttack || !IsValid()) return false;
            await Target.EnsureValidTarget();
            ShouldPulse = true;
            if (await Movement.PullMove(Core.Player.CurrentTarget)) return true;
            if (Target.TargetChanged && RogueSettings.UseOpener && Dots && Core.Player.ClassLevel > 45 && Core.Player.CurrentTarget != null
                && RogueSettings.MinHp < Core.Player.CurrentTarget.CurrentHealthPercent
                && (!RogueSettings.WaitForCooldowns || Spell.GcdMs("Internal Release") < 10 && Spell.GcdMs("Blood for Blood") < 10 //&& Spell.GcdMs("Trick Attack") < 10 
                && Spell.GcdMs("Kassatsu") < 10 && !Core.Player.CurrentTarget.HasAura("Mutilate",true)))
            {
                Target.TargetChanged = false;
                Spell.Opener = true;
                PotionToggle = true;
                OpenerCount = 1;
                OpenerCountToggle = false;
                Logging.Write("[RebornCo] Target Has Changed - Resetting Opener");
            }
            if (RogueSettings.WaitEnergyPull && Core.Player.CurrentTPPercent < RogueSettings.RestEnergy)
            {
                Logging.Write("[RebornCo] Waiting for energy before pull!");
                return true;
            }
            if (MudraReady||Core.Player.HasAura("Mudra"))  await Movement.MoveToTarget();
            if (MudraReady && DateTime.UtcNow.TimeOfDay > MudraTimeReady)
            {
                if (!Core.Player.HasAura("Mudra") && (NinjutsuInCooldown() || NinjutusCooldown < 10))
                {
                    Logging.Write(Colors.Orchid, "[RebornCo] No Mudra?");
                    MudraReady = false;
                }
                if ((Core.Player.CurrentTarget != null && Core.Player.CurrentTarget.InLineOfSight()
                    && (Core.Player.Distance2D(Core.Player.CurrentTarget.Location) < 15
                        || Spell.NoneGcdLast.Equals("Shuriken") && Core.Player.Distance2D(Core.Player.CurrentTarget.Location) < 25)
                        || Spell.NoneGcdLast.Equals("Huton"))
                && await CastNinjutsu(Core.Player.CurrentTarget))
                {
                    Logging.Write(Colors.Orchid, "[RebornCo] Casting Ninjutsu");
                }
                return true;
            }
            if (MudraReady) return false;
            if (Spell.Opener) return await Opener();
            //change pull combos to api
            if (await Spell.Cast("Hide", Core.Player, RogueSettings.UseHide && (Core.Player.ClassLevel > 21 && Core.Player.CurrentTarget!=null && !Core.Player.CurrentTarget.IsBehind && !Core.Player.CurrentTarget.IsFlanking || Core.Player.ClassLevel > 49)
                && !Core.Player.HasAura("Hidden"))) return true;
            if (!Spell.Gcd && await Spell.PullCast("Sneak Attack", Core.Player.CurrentTarget, (RogueSettings.CooldownsUsable || RogueSettings.UseHide) && Core.Player.HasAura("Hidden") && Core.Player.CurrentTarget != null && !Core.Player.CurrentTarget.IsFlanking && !Core.Player.CurrentTarget.IsBehind)) return true;
            if (!Spell.Gcd && await Spell.PullCast("Trick Attack", Core.Player.CurrentTarget, (RogueSettings.CooldownsUsable || RogueSettings.UseHide) && Core.Player.HasAura("Hidden") 
                && Core.Player.CurrentTarget != null
                && (RogueSettings.MinHpCustom && RogueSettings.MinHpTrick < Core.Player.CurrentTarget.CurrentHealthPercent
                || !RogueSettings.MinHpCustom && RogueSettings.MinDotHp < Core.Player.CurrentTarget.CurrentHealthPercent)
    && (RogueSettings.TrickIsBehindAdjustment != 100 && Movement.IsBehind(Core.Player.CurrentTarget, Core.Player)
    || RogueSettings.TrickIsBehindAdjustment == 100 && Core.Player.CurrentTarget.IsBehind))) return true;
            if (!Spell.Gcd && await Spell.PullCast("Shadow Fang", Core.Player.CurrentTarget, Spell.LastCombo == Combo.SpinningEdge && (Spell.CachedCombo == Combo.Flushed|| Spell.CachedCombo == Combo.ShadowFang)
                && !Core.Player.CurrentTarget.HasAura("Shadow Fang", true))) return true;
            if (!Spell.Gcd && await Spell.PullCast("Gust Slash", Core.Player.CurrentTarget, Spell.LastCombo == Combo.SpinningEdge&& (Spell.CachedCombo == Combo.Flushed|| Spell.CachedCombo == Combo.GustSlash))) return true;
            if (!Spell.Gcd && await Spell.PullCast("Dancing Edge", Core.Player.CurrentTarget, Spell.LastCombo == Combo.GustSlash && (Spell.CachedCombo == Combo.Flushed|| Spell.CachedCombo == Combo.DancingEdge)
                && Core.Player.CurrentTarget != null && (Core.Player.CurrentTarget.IsFlanking || !(Core.Player.CurrentTarget.HasAura("Dancing Edge") || Core.Player.CurrentTarget.HasAura("Storm's Eye"))))) return true;
            if (!Spell.Gcd && await Spell.PullCast("Aeolian Edge", Core.Player.CurrentTarget, Spell.LastCombo == Combo.GustSlash&& (Spell.CachedCombo == Combo.Flushed|| Spell.CachedCombo == Combo.AeolianEdge))) return true;
            if (!Spell.Gcd && await Spell.PullCast("Mutilate", Core.Player.CurrentTarget, Core.Player.CurrentTarget != null && Core.Player.CurrentTarget.CurrentHealthPercent > RogueSettings.MinDotHp
                && !Core.Player.CurrentTarget.HasAura("Mutilation", true, RogueSettings.MutilationClip))) return true;
            if (await Spell.PullCast("Spinning Edge", Core.Player.CurrentTarget)) return true;
            return false;
        }

        [Behavior(BehaviorType.Combat)]
        public Composite NinjaCreateBasicCombat()
        {
            return new ActionRunCoroutine(ctx => NinjaBuildBasicCombat()); 
        }
        public static async Task<bool> NinjaBuildBasicCombat()
        {
            if (Core.Player.IsDead || Core.Player.CurrentTarget == null) return false;
            ShouldPulse = true;
            if (MudraReady && DateTime.UtcNow.TimeOfDay > MudraTimeReady)
            {
                if (!Core.Player.HasAura("Mudra") && (NinjutsuInCooldown() || NinjutusCooldown < 10))
                {
                    Logging.Write(Colors.Orchid, "[RebornCo] No Mudra?");
                    MudraReady = false;
                }
                if ((Core.Player.CurrentTarget != null && Core.Player.CurrentTarget.InLineOfSight()
                    && (Core.Player.Distance2D(Core.Player.CurrentTarget.Location) < 15
                        || Spell.NoneGcdLast.Equals("Shuriken") && Core.Player.Distance2D(Core.Player.CurrentTarget.Location) < 25)
                        || Spell.NoneGcdLast.Equals("Huton"))
                && await CastNinjutsu(Core.Player.CurrentTarget))
                {
                    Logging.Write(Colors.Orchid, "[RebornCo] Casting Ninjutsu");
                }
                return true;
            }
            if (MudraReady) return false;
            if (Target.TargetChanged && RogueSettings.UseOpener && Dots && Core.Player.ClassLevel > 45
                && RogueSettings.MinHp < Core.Player.CurrentTarget.CurrentHealthPercent
                && (!RogueSettings.WaitForCooldowns || Spell.GcdMs("Internal Release") < 10 && Spell.GcdMs("Blood for Blood") < 10 //&& Spell.GcdMs("Trick Attack") < 10 
                && Spell.GcdMs("Kassatsu") < 10 && !Core.Player.CurrentTarget.HasAura("Mutilate", true)))
            {
                Target.TargetChanged = false;
                PotionToggle = true;
                Spell.Opener = true;
                OpenerCount = 1;
                OpenerCountToggle = false;
                Logging.Write("[RebornCo] Target " + Core.Player.CurrentTarget.ObjectId + " Has Changed - Resetting Opener");
            }
            if (Core.Player.CurrentTarget != null && MovementManager.IsMoving
                && !(Core.Player.CurrentTarget.InLineOfSight() && Core.Player.CurrentTarget.Distance2D() < Movement.ObjectMeleeRange(Core.Player.CurrentTarget))) return true;
            if (Spell.Opener) return await Opener();
            if (!Spell.Gcd && Spell.LastCombo == Combo.SpinningEdge && Core.Player.CurrentTarget != null) 
            {
                if (Dots && await Spell.CastLock("Shadow Fang", Core.Player.CurrentTarget, Core.Player.ClassLevel > 45
                    && (Spell.CachedCombo == Combo.ShadowFang || Spell.CachedCombo == Combo.Flushed
                && (RogueSettings.MinHpCustom && RogueSettings.MinHpSf < Core.Player.CurrentTarget.CurrentHealthPercent
                || !RogueSettings.MinHpCustom && RogueSettings.MinDotHp < Core.Player.CurrentTarget.CurrentHealthPercent)
                    && !Core.Player.CurrentTarget.HasAura("Shadow Fang", true, RogueSettings.ShadowFangClip) 
                    && (!DancingEdge ||(Core.Player.CurrentTarget.HasAura("Dancing Edge", false, RogueSettings.DancingEdgeClip)
                        || Core.Player.CurrentTarget.HasAura("Storm's Eye", false, RogueSettings.DancingEdgeClip)))
                    ))) return true;
                return await Spell.Cast("Gust Slash", Core.Player.CurrentTarget, (Spell.CachedCombo == Combo.Flushed|| Spell.CachedCombo == Combo.GustSlash));
            }
            if (!Spell.Gcd && Spell.LastCombo == Combo.GustSlash && Core.Player.CurrentTarget != null && Core.Player.ClassLevel > 25)
            {
                if (DancingEdge && await Spell.CastLock("Dancing Edge", Core.Player.CurrentTarget, Core.Player.ClassLevel > 37
                  && (Spell.CachedCombo == Combo.DancingEdge || Spell.CachedCombo == Combo.Flushed
                && (RogueSettings.MinHpCustom && RogueSettings.MinHpDance < Core.Player.CurrentTarget.CurrentHealthPercent
                || !RogueSettings.MinHpCustom && RogueSettings.MinDotHp < Core.Player.CurrentTarget.CurrentHealthPercent)
                  && !(Core.Player.CurrentTarget.HasAura("Dancing Edge", false, RogueSettings.DancingEdgeClip) 
                  || Core.Player.CurrentTarget.HasAura("Storm's Eye", false, RogueSettings.DancingEdgeClip))))) return true;
              return await Spell.Cast("Aeolian Edge", Core.Player.CurrentTarget, Core.Player.ClassLevel > 25 
                  && (Spell.CachedCombo == Combo.Flushed || Spell.CachedCombo == Combo.AeolianEdge));
            }
            if (!Spell.Gcd && await Spell.Cast("Spinning Edge", Core.Player.CurrentTarget, Core.Player.CurrentTarget != null && Core.Player.CurrentTarget.CurrentHealthPercent > RogueSettings.MinDotHp
                    && (Dots && Core.Player.ClassLevel > 45 && !Core.Player.CurrentTarget.HasAura("Shadow Fang", true, RogueSettings.ShadowFangClip)
                    || DancingEdge && Core.Player.ClassLevel > 37 && !(Core.Player.CurrentTarget.HasAura("Dancing Edge", false, RogueSettings.DancingEdgeClip)
                  || Core.Player.CurrentTarget.HasAura("Storm's Eye", false, RogueSettings.DancingEdgeClip))))) return true;
            if (!Spell.Gcd && Dots && await Spell.CastLock("Mutilate", Core.Player.CurrentTarget, Core.Player.CurrentTarget != null
                && (RogueSettings.MinHpCustom && RogueSettings.MinHpMut < Core.Player.CurrentTarget.CurrentHealthPercent
                || !RogueSettings.MinHpCustom && RogueSettings.MinDotHp < Core.Player.CurrentTarget.CurrentHealthPercent)
                && !Core.Player.CurrentTarget.HasAura("Mutilation", true, RogueSettings.MutilationClip))) return true;
            if (!Spell.Gcd && await Spell.Cast("Death Blossom", Core.Player.CurrentTarget, RogueSettings.Aoe && Target.mNearbyEnemyUnits() != null && Target.mNearbyEnemyUnits().Count(unit => unit.Distance2D() <= 5) >= RogueSettings.AoeCount)) return true;
            if (!Spell.Gcd && await Spell.Cast("Throwing Dagger", Core.Player.CurrentTarget, Core.Player.CurrentTarget != null && Core.Player.CurrentTarget.Distance2D() > Movement.MeleeRange + 4)) return true;
           // if (!Gcd && await Spell.Cast("Haymaker", Core.Player.CurrentTarget, true, false, false, true)&&Spell.GcdRogue())) return true;
            if (!Spell.Gcd && Dots && await Spell.Cast("Virus", Core.Player.CurrentTarget, Core.Player.CurrentTarget != null && !Core.Player.CurrentTarget.HasAura("Virus"))) return true; 
            if (!Spell.Gcd && Dots && await Spell.CastLock("Venomous Bite", Core.Player.CurrentTarget, Core.Player.CurrentTarget != null && Core.Player.CurrentTarget.CurrentHealthPercent > RogueSettings.MinDotHp && !Core.Player.CurrentTarget.HasAura("Venomous Bite"))) return true;
            if (!Spell.Gcd && Dots && await Spell.CastLock("Fracture", Core.Player.CurrentTarget, Core.Player.CurrentTarget != null && !Core.Player.CurrentTarget.HasAura("Fracture", true))) return true;
            if (!Spell.Gcd && await Spell.Cast("Spinning Edge", Core.Player.CurrentTarget)) return true;
            if (Spell.GcdTime < RogueSettings.NoneGcdWindowEnd) return false;
            if (await Spell.NoneGcdCast("Assassinate", Core.Player.CurrentTarget, Core.Player.CurrentTarget != null 
                && RogueSettings.Assassinate && Core.Player.CurrentTarget.CurrentHealthPercent < 20)) return true; 
            if (await Spell.NoneGcdCast("Mercy Stroke", Core.Player.CurrentTarget, Core.Player.CurrentTarget != null && Core.Player.CurrentTarget.CurrentHealthPercent < 20)) return true;
            if (await Spell.NoneGcdCast("Mug", Core.Player.CurrentTarget, true)) return true; 
            if (await Spell.NoneGcdCast("Jugulate", Core.Player.CurrentTarget, RogueSettings.JugulateDps))  return true; 
            return false;
        }

        public static async Task<bool> Opener()
        {
            if (Target.TargetChanged)
            {
                Target.TargetChanged = false;
            }
            if ((RogueSettings.HutonNoTarget ||  Core.Player.CurrentTarget != null && Core.Player.CurrentTarget.InLineOfSight()
                    && Core.Player.CurrentTarget.Distance2D() > Movement.ObjectMeleeRange(Core.Player.CurrentTarget) + 6)
               && (Spell.NoneGcdCache == null || Spell.NoneGcdCache.Equals("Huton")) 
               && Core.Player.ClassLevel > 44 && NinjutsuCanMudra()
               && !Core.Player.HasAura("Huton", false, RogueSettings.HutonClip))
            {
                Spell.NoneGcdCache = "Huton";
                Logging.Write(Colors.Orchid, "[RebornCo] Preparing Opener Huton");
                await Coroutine.Wait(4000, () => CastMudra("Jin"));
                MudraSafe = false;
                MudraReady = true;
                if (RogueSettings.MoveStopNinjutsu) Movement.StopMove();
                else await Movement.MoveToTarget();
                await Coroutine.Wait(4000, () => CastMudra("Chi"));
                MudraSafe = false;
                if (!RogueSettings.MoveStopNinjutsu) await Movement.MoveToTarget();
                await Coroutine.Wait(4000, () => CastMudra("Ten"));
                MudraSafe = false;
                MudraTimeReady = DateTime.UtcNow.TimeOfDay + TimeSpan.FromMilliseconds(510);
                return false;
            }

            if (Spell.Gcd && OpenerCountToggle)
            {
                if (OpenerCount > 3)
                {
                    Spell.Opener = false;
                    OpenerCount = 1;
                    Logging.Write(Colors.Orchid, "[RebornCo] Opener Complete");
                    return false;
                }
                OpenerCountToggle = false;
                OpenerCount++;
                Logging.Write(Colors.Orchid, "[RebornCo] Opener Action Confirmed");
            }
            if (Core.Player.CurrentTarget == null) return false;
            if (RogueSettings.B4BBeforePull && await Spell.NoneGcdCast("Blood for Blood", Core.Player, RogueSettings.CooldownsUsable &&
                Core.Player.CurrentTarget.Distance2D() < Movement.ObjectMeleeRange(Core.Player.CurrentTarget) + 3)) return true;
            if (RogueSettings.Order == RogueOpeners.DancingEdgeShadowFangMutilate)
                return await OpenerDancingEdgeShadowFangMutilate();
            if (RogueSettings.Order == RogueOpeners.DancingEdgeMutilateShadowFang)
                return await OpenerDancingEdgeMutilateShadowFang();
            if (RogueSettings.Order == RogueOpeners.MutilateDancingEdgeShadowFang)
                return await OpenerMutilateDancingEdgeShadowFang();
            if (RogueSettings.Order == RogueOpeners.MutilateShadowFangDancingEdge)
                return await OpenerMutilateShadowFangDancingEdge();
            if (RogueSettings.Order == RogueOpeners.ShadowFangDancingEdgeMutilate)
                return await OpenerShadowFangDancingEdgeMutilate();
            if (RogueSettings.Order == RogueOpeners.ShadowFangMutilateDancingEdge)
                return await OpenerShadowFangMutilateDancingEdge();
            Logging.Write(Colors.Orchid, "[RebornCo] Opener Setting's Error");
            return false;
        }

        public static async Task<bool> OpenerNoneGcd()
        {
            if (Spell.GcdTime < RogueSettings.NoneGcdWindowEnd) return false;
            if (await Spell.NoneGcdCast("Blood for Blood", Core.Player,true)) return true;
            if (await Spell.NoneGcdCast("Internal Release", Core.Player, true)) return true; 
            NinjutusCooldown = Spell.GetSpellData("Ninjutsu").Cooldown.TotalMilliseconds;
            if (RogueSettings.CooldownsUsable && Spell.Potion != null && Spell.Potion.IsValid
    && (!RogueSettings.PotionWaitForIrAndB4B || Spell.GcdMs("Internal Release") > 80 && Spell.GcdMs("Blood for Blood") > 80)
     && Spell.Potion.CanUse(Core.Player) && Spell.Potion.Name.Equals(RogueSettings.PotionName))
            {
                Spell.Potion.UseItem(Core.Player);
                if (Spell.NoneGcdCache == null)
                {
                    if (RogueSettings.PotionForce || PotionToggle) Spell.NoneGcdCache = "Potion";
                    PotionToggle = false;
                }
            }
            if (Spell.NoneGcdCache == null && Core.Player.ClassLevel > 49 && CanTrick() && NinjutsuCanMudra()
                && Core.Player.CurrentTarget != null && Core.Player.Distance2D(Core.Player.CurrentTarget.Location) < 15
                && (!RogueSettings.SuitonWaitForIrAndB4B
                    || ((Spell.NoneGcdLast.Equals("Internal Release") || Spell.NoneGcdLast.Equals("Potion") || Spell.GcdMs("Internal Release") > 80))
                        && (Spell.NoneGcdLast.Equals("Blood for Blood") || Spell.GcdMs("Blood for Blood") > 80)))
            {
                Spell.NoneGcdCache = "Suiton";
                Logging.Write(Colors.Orchid, "[RebornCo] Preparing Suiton");
                await Coroutine.Wait(4000, () => CastMudra("Ten"));
                MudraSafe = false;
                MudraReady = true;
                if (RogueSettings.MoveStopNinjutsu) Movement.StopMove();
                else await Movement.MoveToTarget();
                await Coroutine.Wait(4000, () => CastMudra("Chi"));
                MudraSafe = false;
                if (!RogueSettings.MoveStopNinjutsu) await Movement.MoveToTarget();
                await Coroutine.Wait(4000, () => CastMudra("Jin"));
                MudraSafe = false;
                MudraTimeReady = DateTime.UtcNow.TimeOfDay + TimeSpan.FromMilliseconds(510);
                return true;
            }
            if ((Spell.NoneGcdCache == null || Spell.NoneGcdCache.Equals("Trick Attack"))
                && Core.Player.ClassLevel > 49 && (Spell.NoneGcdLast.Equals("Suiton") || Core.Player.HasAura("Hidden") || Core.Player.HasAura("Suiton")) 
    && Core.Player.CurrentTarget != null && (RogueSettings.TrickIsBehindAdjustment != 100 && Movement.IsBehind(Core.Player.CurrentTarget, Core.Player)
    || RogueSettings.TrickIsBehindAdjustment == 100 && Core.Player.CurrentTarget.IsBehind))
            {
                await Spell.NoneGcdCast("Trick Attack", Core.Player.CurrentTarget, true, true);
                return true;
            }
            if (await Spell.NoneGcdCast("Kassatsu", Core.Player, RogueSettings.CooldownsUsable && (Spell.NoneGcdLast.Equals("Kassatsu") || Spell.NoneGcdLast.Equals("Trick Attack")))) return true;
            if (Spell.NoneGcdCache == null && Core.Player.CurrentTarget != null && Core.Player.CurrentTarget.InLineOfSight()
         && (RogueSettings.ShurikenAlways
         || RogueSettings.ShurikenCheckMobs && RogueSettings.ShurikenList.Any(n => !string.IsNullOrEmpty(n) && Core.Player.CurrentTarget.Name.ToLower().Contains(n)))
         && Core.Player.Distance2D(Core.Player.CurrentTarget.Location) < 25
         && (NinjutsuCanMudra() || Spell.NoneGcdLast.Equals("Kassatsu")))
            {
                Spell.NoneGcdCache = "Shuriken";
                Logging.Write(Colors.Orchid, "[RebornCo] Preparing Shuriken!");
                await Coroutine.Wait(4000, () => CastMudra("Ten"));
                MudraSafe = false;
                MudraTimeReady = DateTime.UtcNow.TimeOfDay + TimeSpan.FromMilliseconds(510);
                MudraReady = true;
                return true;
            }
            if (Spell.NoneGcdCache == null && Core.Player.CurrentTarget != null && Core.Player.CurrentTarget.InLineOfSight()
                && Core.Player.Distance2D(Core.Player.CurrentTarget.Location) < 15
         && (NinjutsuCanMudra() || Spell.NoneGcdLast.Equals("Kassatsu")))
            {
                Spell.NoneGcdCache = "Raiton";
                Logging.Write(Colors.Orchid, "[RebornCo] Preparing Raiton");
                await Coroutine.Wait(4000, () => CastMudra("Ten"));
                MudraSafe = false;
                MudraReady = true;
                if (!RogueSettings.MoveStopNinjutsu) await Movement.MoveToTarget();
                await Coroutine.Wait(4000, () => CastMudra("Chi"));
                MudraSafe = false;
                MudraTimeReady = DateTime.UtcNow.TimeOfDay + TimeSpan.FromMilliseconds(510);
                return true;
            }
            if (await Spell.NoneGcdCast("Mug", Core.Player.CurrentTarget,true)) return true; 
            if (await Spell.NoneGcdCast("Jugulate", Core.Player.CurrentTarget, RogueSettings.JugulateDps))return true; 
            return false;
        }

        public static async Task<bool> OpenerDancingEdgeShadowFangMutilate()
        {
            if (!RogueSettings.AeolianWhileDancingHalted && !DancingEdge && OpenerCount == 1) OpenerCount++;
            if (!Spell.Gcd && Spell.LastCombo == Combo.SpinningEdge)
            {
                if (await Spell.CastLock("Shadow Fang", Core.Player.CurrentTarget, OpenerCount == 2))
                {
                    OpenerCountToggle = true;
                    return true;
                }
                return await Spell.Cast("Gust Slash", Core.Player.CurrentTarget, OpenerCount == 1 || OpenerCount == 4);
            }
            if (!Spell.Gcd && Spell.LastCombo == Combo.GustSlash)
            {
                OpenerCountToggle = true;
                if (DancingEdge && await Spell.CastLock("Dancing Edge", Core.Player.CurrentTarget, Core.Player.ClassLevel > 37
                  && (Spell.CachedCombo == Combo.DancingEdge || Spell.CachedCombo == Combo.Flushed
                && (RogueSettings.MinHpCustom && RogueSettings.MinHpDance < Core.Player.CurrentTarget.CurrentHealthPercent
                || !RogueSettings.MinHpCustom && RogueSettings.MinDotHp < Core.Player.CurrentTarget.CurrentHealthPercent)
                  && !(Core.Player.CurrentTarget.HasAura("Dancing Edge", false, RogueSettings.DancingEdgeClip)
                  || Core.Player.CurrentTarget.HasAura("Storm's Eye", false, RogueSettings.DancingEdgeClip))))) return true;
                return await Spell.Cast("Aeolian Edge", Core.Player.CurrentTarget, (Spell.CachedCombo == Combo.Flushed || Spell.CachedCombo == Combo.AeolianEdge));
            }
            if (!Spell.Gcd && await Spell.Cast("Spinning Edge", Core.Player.CurrentTarget, OpenerCount < 3 || OpenerCount == 4)) return true;
            if (!Spell.Gcd && Dots && await Spell.CastLock("Mutilate", Core.Player.CurrentTarget, OpenerCount == 3))
            {
                OpenerCountToggle = true;
                return true;
            }
            return await OpenerNoneGcd();
        }
        public static async Task<bool> OpenerDancingEdgeMutilateShadowFang()
        {
            if (!RogueSettings.AeolianWhileDancingHalted && !DancingEdge && OpenerCount == 1) OpenerCount++;
            if (!Spell.Gcd && Spell.LastCombo == Combo.SpinningEdge)
            {
                if (await Spell.CastLock("Shadow Fang", Core.Player.CurrentTarget, OpenerCount == 3))
                {
                    OpenerCountToggle = true;
                    return true;
                }
                return await Spell.Cast("Gust Slash", Core.Player.CurrentTarget, OpenerCount == 1 || OpenerCount == 4);
            }
            if (!Spell.Gcd && Spell.LastCombo == Combo.GustSlash)
            {
                OpenerCountToggle = true;
                if (DancingEdge && await Spell.CastLock("Dancing Edge", Core.Player.CurrentTarget, Core.Player.ClassLevel > 37
                  && (Spell.CachedCombo == Combo.DancingEdge || Spell.CachedCombo == Combo.Flushed
                && (RogueSettings.MinHpCustom && RogueSettings.MinHpDance < Core.Player.CurrentTarget.CurrentHealthPercent
                || !RogueSettings.MinHpCustom && RogueSettings.MinDotHp < Core.Player.CurrentTarget.CurrentHealthPercent)
                  && !(Core.Player.CurrentTarget.HasAura("Dancing Edge", false, RogueSettings.DancingEdgeClip)
                  || Core.Player.CurrentTarget.HasAura("Storm's Eye", false, RogueSettings.DancingEdgeClip))))) return true;
                return await Spell.Cast("Aeolian Edge", Core.Player.CurrentTarget, (Spell.CachedCombo == Combo.Flushed || Spell.CachedCombo == Combo.AeolianEdge));
            }
            if (!Spell.Gcd && await Spell.Cast("Spinning Edge", Core.Player.CurrentTarget, OpenerCount == 1 || OpenerCount == 3 || OpenerCount == 4)) return true;
            if (!Spell.Gcd && Dots && await Spell.CastLock("Mutilate", Core.Player.CurrentTarget, OpenerCount == 2))
            {
                OpenerCountToggle = true;
                return true;
            }
            return await OpenerNoneGcd();
        }
        public static async Task<bool> OpenerMutilateDancingEdgeShadowFang()
        {
            if (!RogueSettings.AeolianWhileDancingHalted && !DancingEdge && OpenerCount == 2) OpenerCount++;
            if (!Spell.Gcd && Spell.LastCombo == Combo.SpinningEdge)
            {
                if (await Spell.CastLock("Shadow Fang", Core.Player.CurrentTarget, OpenerCount == 3))
                {
                    OpenerCountToggle = true;
                    return true;
                }
                return await Spell.Cast("Gust Slash", Core.Player.CurrentTarget, OpenerCount == 2 || OpenerCount == 4);
            }
            if (!Spell.Gcd && Spell.LastCombo == Combo.GustSlash)
            {
                OpenerCountToggle = true;
                if (DancingEdge && await Spell.CastLock("Dancing Edge", Core.Player.CurrentTarget, Core.Player.ClassLevel > 37
                  && (Spell.CachedCombo == Combo.DancingEdge || Spell.CachedCombo == Combo.Flushed
                && (RogueSettings.MinHpCustom && RogueSettings.MinHpDance < Core.Player.CurrentTarget.CurrentHealthPercent
                || !RogueSettings.MinHpCustom && RogueSettings.MinDotHp < Core.Player.CurrentTarget.CurrentHealthPercent)
                  && !(Core.Player.CurrentTarget.HasAura("Dancing Edge", false, RogueSettings.DancingEdgeClip)
                  || Core.Player.CurrentTarget.HasAura("Storm's Eye", false, RogueSettings.DancingEdgeClip))))) return true;
                return await Spell.Cast("Aeolian Edge", Core.Player.CurrentTarget, (Spell.CachedCombo == Combo.Flushed || Spell.CachedCombo == Combo.AeolianEdge));
            }
            if (!Spell.Gcd && await Spell.Cast("Spinning Edge", Core.Player.CurrentTarget, OpenerCount > 1)) return true;
            if (!Spell.Gcd && Dots && await Spell.CastLock("Mutilate", Core.Player.CurrentTarget, OpenerCount == 1))
            {
                OpenerCountToggle = true;
                return true;
            }
            return await OpenerNoneGcd();
        }
        public static async Task<bool> OpenerMutilateShadowFangDancingEdge()
        {
            if (!RogueSettings.AeolianWhileDancingHalted && !DancingEdge && OpenerCount == 3) OpenerCount++;
            if (!Spell.Gcd && Spell.LastCombo == Combo.SpinningEdge)
            {
                if (await Spell.CastLock("Shadow Fang", Core.Player.CurrentTarget, OpenerCount == 2))
                {
                    OpenerCountToggle = true;
                    return true;
                }
                return await Spell.Cast("Gust Slash", Core.Player.CurrentTarget, OpenerCount == 3 || OpenerCount == 4);
            }
            if (!Spell.Gcd && Spell.LastCombo == Combo.GustSlash)
            {
                OpenerCountToggle = true;
                if (DancingEdge && await Spell.CastLock("Dancing Edge", Core.Player.CurrentTarget, Core.Player.ClassLevel > 37
                  && (Spell.CachedCombo == Combo.DancingEdge || Spell.CachedCombo == Combo.Flushed
                && (RogueSettings.MinHpCustom && RogueSettings.MinHpDance < Core.Player.CurrentTarget.CurrentHealthPercent
                || !RogueSettings.MinHpCustom && RogueSettings.MinDotHp < Core.Player.CurrentTarget.CurrentHealthPercent)
                  && !(Core.Player.CurrentTarget.HasAura("Dancing Edge", false, RogueSettings.DancingEdgeClip)
                  || Core.Player.CurrentTarget.HasAura("Storm's Eye", false, RogueSettings.DancingEdgeClip))))) return true;
                return await Spell.Cast("Aeolian Edge", Core.Player.CurrentTarget, (Spell.CachedCombo == Combo.Flushed || Spell.CachedCombo == Combo.AeolianEdge));
            }
            if (!Spell.Gcd && await Spell.Cast("Spinning Edge", Core.Player.CurrentTarget, OpenerCount > 1)) return true;
            if (!Spell.Gcd && Dots && await Spell.CastLock("Mutilate", Core.Player.CurrentTarget, OpenerCount == 1))
            {
                OpenerCountToggle = true;
                return true;
            }
            return await OpenerNoneGcd();
        }
        public static async Task<bool> OpenerShadowFangDancingEdgeMutilate()
        {
            if (!RogueSettings.AeolianWhileDancingHalted && !DancingEdge && OpenerCount == 2) OpenerCount++;
            if (!Spell.Gcd && Spell.LastCombo == Combo.SpinningEdge)
            {
                if (await Spell.CastLock("Shadow Fang", Core.Player.CurrentTarget, OpenerCount == 1))
                {
                    OpenerCountToggle = true;
                    return true;
                }
                return await Spell.Cast("Gust Slash", Core.Player.CurrentTarget, OpenerCount == 2 || OpenerCount == 4);
            }
            if (!Spell.Gcd && Spell.LastCombo == Combo.GustSlash)
            {
                OpenerCountToggle = true;
                if (DancingEdge && await Spell.CastLock("Dancing Edge", Core.Player.CurrentTarget, Core.Player.ClassLevel > 37
                  && (Spell.CachedCombo == Combo.DancingEdge || Spell.CachedCombo == Combo.Flushed
                && (RogueSettings.MinHpCustom && RogueSettings.MinHpDance < Core.Player.CurrentTarget.CurrentHealthPercent
                || !RogueSettings.MinHpCustom && RogueSettings.MinDotHp < Core.Player.CurrentTarget.CurrentHealthPercent)
                  && !(Core.Player.CurrentTarget.HasAura("Dancing Edge", false, RogueSettings.DancingEdgeClip)
                  || Core.Player.CurrentTarget.HasAura("Storm's Eye", false, RogueSettings.DancingEdgeClip))))) return true;
                return await Spell.Cast("Aeolian Edge", Core.Player.CurrentTarget, (Spell.CachedCombo == Combo.Flushed || Spell.CachedCombo == Combo.AeolianEdge));
            }
            if (!Spell.Gcd && await Spell.Cast("Spinning Edge", Core.Player.CurrentTarget, OpenerCount == 1 || OpenerCount == 2 || OpenerCount == 4)) return true;
            if (!Spell.Gcd && Dots && await Spell.CastLock("Mutilate", Core.Player.CurrentTarget, OpenerCount == 3))
            {
                OpenerCountToggle = true;
                return true;
            }
            return await OpenerNoneGcd();
        }
        public static async Task<bool> OpenerShadowFangMutilateDancingEdge()
        {
            if (!RogueSettings.AeolianWhileDancingHalted && !DancingEdge && OpenerCount == 3) OpenerCount++;
            if (!Spell.Gcd && Spell.LastCombo == Combo.SpinningEdge)
            {
                if (await Spell.CastLock("Shadow Fang", Core.Player.CurrentTarget, OpenerCount == 1))
                {
                    OpenerCountToggle = true;
                    return true;
                }
                return await Spell.Cast("Gust Slash", Core.Player.CurrentTarget, OpenerCount == 3 || OpenerCount == 4);
            }
            if (!Spell.Gcd && Spell.LastCombo == Combo.GustSlash)
            {
                OpenerCountToggle = true;
                if (DancingEdge && await Spell.CastLock("Dancing Edge", Core.Player.CurrentTarget, Core.Player.ClassLevel > 37
                  && (Spell.CachedCombo == Combo.DancingEdge || Spell.CachedCombo == Combo.Flushed
                && (RogueSettings.MinHpCustom && RogueSettings.MinHpDance < Core.Player.CurrentTarget.CurrentHealthPercent
                || !RogueSettings.MinHpCustom && RogueSettings.MinDotHp < Core.Player.CurrentTarget.CurrentHealthPercent)
                  && !(Core.Player.CurrentTarget.HasAura("Dancing Edge", false, RogueSettings.DancingEdgeClip)
                  || Core.Player.CurrentTarget.HasAura("Storm's Eye", false, RogueSettings.DancingEdgeClip))))) return true;
                return await Spell.Cast("Aeolian Edge", Core.Player.CurrentTarget, (Spell.CachedCombo == Combo.Flushed || Spell.CachedCombo == Combo.AeolianEdge));
            }
            if (!Spell.Gcd && await Spell.Cast("Spinning Edge", Core.Player.CurrentTarget, OpenerCount == 1 || OpenerCount == 3 || OpenerCount == 4)) return true;
            if (!Spell.Gcd && Dots && await Spell.CastLock("Mutilate", Core.Player.CurrentTarget, OpenerCount == 2))
            {
                OpenerCountToggle = true;
                return true;
            }
            return await OpenerNoneGcd();
        }
        public static bool CastMudra(string s)
        {    
            if (DateTime.UtcNow.TimeOfDay < MudraStep) return false;
            var cd = Spell.GetSpellData(s).Cooldown.TotalMilliseconds;
            if (MudraSafe && cd > 200)
            {
                MudraStep = DateTime.UtcNow.TimeOfDay + TimeSpan.FromMilliseconds(cd);
                return true;
            }
            if (!MudraSafe && cd < 10)
            {
                Logging.Write(Colors.OrangeRed, "[RebornCo] Casting: " + s);
                MudraStep = DateTime.UtcNow.TimeOfDay + TimeSpan.FromMilliseconds(150);
                MudraSafe = true;
                return false;
            }
            if (!MudraSafe || cd > 10) return false;
            Actionmanager.DoAction(s, Core.Player);
            MudraStep = DateTime.UtcNow.TimeOfDay + TimeSpan.FromMilliseconds(150);
            return false;
        }
        public static bool CanTrick()
        {//might want to increase cooldown check
            if (Extensions.DoubleCastPreventionDict.Contains(null, "Trick Attack")) return false;
            SpellData data;
            if (!Actionmanager.CurrentActions.TryGetValue("Trick Attack", out data)) return false;
            var cooldown = data.Cooldown.TotalMilliseconds;
            if (cooldown < 2500 || Math.Abs(data.BaseCooldown.TotalMilliseconds - cooldown) < 50)
            {
                return true;
            }
            Extensions.UpdateDoubleCastDictSpecific("Trick Attack", null, (cooldown - 2000 - WindowSettings.SpellQueue)/1000);
            return false;
        }

#pragma warning disable 1998
        public static async Task<bool> CastNinjutsu(GameObject o)
#pragma warning restore 1998
        {
            if (Core.Player == null) return false;
            return !NinjutsuInCooldown() && Actionmanager.DoAction("Ninjutsu", (o ?? Core.Player));
        }

        public static bool NinjutsuInCooldown()
        {
            return (NinjutusCooldown > 540);
        }

        public static bool NinjutsuCanMudra()
        {
            return (NinjutusCooldown < 200);
        }

        public static TimeSpan MudraTimeReady, MudraStep;
        public static bool Dots = true, DancingEdge = true, PotionToggle, OpenerCountToggle,
            NinjutsuInCooldownCache, NinjutsuCanMudraCache, MudraSafe;
        public static byte OpenerCount;
        public static double NinjutusCooldown;
    }
}
